package com.github.baichuan.application.dashboard.config;

import com.github.baichuan.web.gateway.HeaderAppendAuthorizationFilter;
import com.github.baichuan.web.gateway.HeaderAppendMemberUidFilter;
import com.github.baichuan.web.security.JwtCodec;
import com.github.baichuan.web.security.PrincipalPayload;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.http.CacheControl;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;

import java.util.concurrent.TimeUnit;

@Configuration
@Slf4j
public class Route {
    @Autowired
    private Environment env;

    @Value("${service.application-skeleton.code}")
    private String applicationCode;
    @Value("${service.application-skeleton.url}")
    private String facilitiesUrl;
    @Value("${service.file.url}")
    private String fileUrl;

    @Bean
    public RouterFunction<ServerResponse> defaultRouter(@Value("file:./public/index.html") final Resource indexHtml) {
        return RouterFunctions.route(RequestPredicates.GET("/"),
                request -> ServerResponse.ok()
                        .cacheControl(CacheControl.noStore())
                        .cacheControl(CacheControl.maxAge(-1, TimeUnit.SECONDS))
                        .contentType(MediaType.TEXT_HTML).bodyValue(indexHtml));
    }

    @Bean
    public RouterFunction<ServerResponse> htmlRouter(@Value("file:./public/index.html") final Resource indexHtml) {
        return RouterFunctions.route(RequestPredicates.GET("/index.html"),
                request -> ServerResponse.ok()
                        .cacheControl(CacheControl.noStore())
                        .cacheControl(CacheControl.maxAge(-1, TimeUnit.SECONDS))
                        .contentType(MediaType.TEXT_HTML).bodyValue(indexHtml));
    }

    @Bean
    public RouteLocator routes(RouteLocatorBuilder builder, JwtCodec<? extends PrincipalPayload> jwt){
        HeaderAppendAuthorizationFilter appendAuthorizationFilter = new HeaderAppendAuthorizationFilter(jwt);
        HeaderAppendMemberUidFilter appendMemberUidFilter = new HeaderAppendMemberUidFilter(jwt);

        return builder.routes()
                .route("forbidden", r -> r.path("/factory/schedule-job/**")
                        .filters(f -> f.setStatus(HttpStatus.FORBIDDEN))
                        .uri("http://forbidden")
                )
//                .route("member", r -> r.path("/member/**")
//                        .filters(f -> f.filter(appendMemberUidFilter)
//                                .addRequestHeader("x-application-code", applicationCode)
//                                .rewritePath("/(?<segment>.*)", "/application/$\\{segment}"))
//                        .uri(facilitiesUrl))
                .route("app-release-file", r -> r.path("/app-release-file/**")
                        .filters(f -> f.rewritePath("(?<segment>.*)", "$\\{segment}"))
                        .uri(fileUrl))
                .route("facilities", r -> r.path("/**")
                        .filters(f -> f.filter(appendAuthorizationFilter)
                                .filters(appendMemberUidFilter)
//                                .addRequestHeader("x-application-code", applicationCode)
                                .rewritePath("/(?<segment>.*)", "/$\\{segment}"))
                        .uri(facilitiesUrl)
                )
                .build();
    }
}
